package com.huwaiwai.completablefuture;


import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * Created by hww on 2018/8/28 下午8:39.
 */
public class Test {

    static ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

    static String product = "iphone666s";

    static List<Shop> shops = Arrays.asList(new Shop("淘宝"),
            new Shop("天猫"),
            new Shop("京东"),
            new Shop("亚马逊"),
            new Shop("苏宁"));


    private static void test01() {
        long start = System.nanoTime();
        List<String> list = shops.stream()
                .map(shop ->
                        String.format("%s price is %.2f RMB",
                                shop.getName(),
                                shop.getPrice(product)))

                .collect(Collectors.toList());
        System.out.println(list);
        System.out.println("Done in " + (System.nanoTime() - start) / 1_000_000 + " ms");
    }

    public static void test02() {
        long start = System.nanoTime();
        List<String> list = shops.parallelStream()
                .map(shop ->
                        String.format("%s price is %.2f RMB",
                                shop.getName(),
                                shop.getPrice(product)))
                .collect(Collectors.toList());
        System.out.println(list);
        System.out.println("Done in " + (System.nanoTime() - start) / 1_000_000 + " ms");
    }

    public static void test03() {
        long start = System.nanoTime();
        List<CompletableFuture<String>> futures = shops.stream()
                .map(shop -> CompletableFuture.supplyAsync(
                        () -> String.format("%s price is %.2f RMB",
                                shop.getName(),
                                shop.getPrice(product)), executorService)
                )
                .collect(Collectors.toList());
        List<String> list = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        System.out.println(list);
        System.out.println("Done in " + (System.nanoTime() - start) / 1_000_000 + " ms");
    }


    public static void main(String[] args) {
        System.out.println(ForkJoinPool.commonPool());
        System.out.println(Runtime.getRuntime().availableProcessors());
        test01();
        test02();
        test03();
    }


    /**
     * 测试同步API
     */
    public static void testgetPrice() {
        Shop shop = new Shop("Best Shop");
        long start = System.nanoTime();
        double price = shop.getPrice("mac book pro");
        System.out.printf(shop.getName() + " Price is %.2f%n", price);
        long invocationTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("同步方法调用花费时间:--- " + invocationTime + " --- msecs");


        //...其他操作
        doSomethingElse();
        long retrievalTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("同步方法返回价格所需时间: --- " + retrievalTime + " ---msecs");

    }


    /**
     * 测试异步API
     */
    public static void testAsync() {
        Shop shop = new Shop("Best Shop");
        long start = System.nanoTime();
        Future<Double> futurePrice = shop.getPriceAsync("mac book pro");
        long invocationTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("异步方法调用花费时间: --- " + invocationTime + " --- msecs");


        //...其他操作
        doSomethingElse();

        //从future对象中读取价格,如果价格未知,则发生阻塞.
        try {
            Double price = futurePrice.get();
            System.out.printf(shop.getName() + " Price is %.2f%n", price);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        long retrievalTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("异步方法返回价格所需时间: --- " + retrievalTime + " ---msecs");
    }


    /**
     * 其它操作
     */
    public static void doSomethingElse() {
        try {
            Thread.sleep(1_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


}
